home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / WWW / httpd_1.5.export / cgi-bin / mail < prev    next >
Encoding:
Text File  |  1995-11-10  |  12.9 KB  |  342 lines

  1. #!/usr/local/bin/perl 
  2.  
  3. # ======================================================================
  4. # WebMonitor Standalone Module: mail
  5. #
  6. #                               CGI script for providing form and script
  7. #                                to send mail to configured system users
  8. #
  9. # required files: mail.list
  10. #                                     Text file with users nicknames and
  11. #                                       email addresses in the format of
  12. #                                             <nickname>:<email address>
  13. #                      Keep "mail.list" in same directory as mail script
  14. #                                 NOTE: you can even have group aliases!
  15. #                                just separate the addresses with commas
  16. #         Make sure you 'chmod 0644 mail.list' so the server can read it
  17. #                             +-----------------------------------------
  18. #                   Example:  |webmaster:admin@machine
  19. #                             |john-doe:jdoe
  20. #                             |carlos:cpero@ncsa.uiuc.edu
  21. #                             |group:leader@domain.com,member@domain.com
  22. #                             +-----------------------------------------
  23. # ======================================================================
  24. # Carlos A. Pero (cpero@ncsa.uiuc.edu)              last update 10/17/95
  25. # ======================================================================
  26. # Documentation for WebMonitor can be found at
  27. #                          <URL:http://hoohoo.ncsa.uiuc.edu/webmonitor/>
  28. # ======================================================================
  29. # This code is in the public domain. Specifically, we give to the public
  30. # domain all rights for future licensing of the source code, all resale
  31. # rights, and all publishing rights.
  32. # We ask, but do not require, that the following message be included in
  33. # all derived works:
  34. # Portions developed at the National Center for Supercomputing
  35. # Applications at the University of Illinois at Urbana-Champaign.
  36. #
  37. # THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED,
  38. # FOR THE SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT
  39. # LIMITATION, WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A
  40. # PARTICULAR PURPOSE.
  41. # ======================================================================
  42. # For the greatest security, this script relies on a 'mail.list' file
  43. # with a list of authorized nicknames and email address which can receive
  44. # email through this mail script.
  45. #
  46. # For greater scalability, the '@AUTHDOMAINS' array can be used to store
  47. # a list of domains.  Any email address ending with one of these domains
  48. # can use this script to receive email.  In this case, the full email
  49. # address becomes the 'nickname'.
  50. # ======================================================================
  51. # This script can be referenced 2 ways for the best flexibility:
  52. #
  53. # DIRECTLY, <A HREF="/cgi-bin/mail?nickname">
  54. # This will generate an email form for the person named in 'nickname',
  55. # and if they exist in the 'mail.list' file.
  56. # If no 'nickname' is specified in the QUERY_STRING when the script is
  57. # first invoked, or the nickname cannot be found in the 'mail.list', 
  58. # an email form with a SELECT box of all valid nicknames is generated.
  59. # When the email form is submitted, it will call itself via method of POST,
  60. # and send the email to the recipient, outputting a confirmation message.
  61. # If the HTTP_REFERER was trasmitted when the script was first invoked,
  62. # there will be a hyperlink available to go back to that page (such as
  63. # the user's home page).
  64. #
  65. # FORWARDING RESULTS, <FORM METHOD="POST" ACTION="/cgi-bin/mail?nickname">
  66. # This will forward the results from the FORM, which can exist anywhere,
  67. # to the recipient specified by 'nickname'.  Since the 'nickname' is in
  68. # the QUERY_STRING, the FORM *must* use the METHOD="POST", otherwise the
  69. # recipient's nickname will be blown away.
  70. # Users may want to include a:
  71. #    <INPUT TYPE="hidden" NAME="next-url" VALUE="/~user/received.html">
  72. # If this is present in the FORM input, the client will be redirected
  73. # to this HTML file as a confirmation message instead of the default.
  74. # In addition, the user can also define any of the following input names
  75. # in their form to better customize the output mailed back to them.
  76. #    <INPUT TYPE="hidden" NAME="subject" VALUE="My survey results">
  77. #    <INPUT TYPE="hidden" NAME="from-name" VALUE="Average Web user">
  78. #    <INPUT TYPE="hidden" NAME="from-email" VALUE="jdoe@domain.com">
  79. # These values will then be used in the header of the email message.
  80. # Otherwise, default values will be substituted.
  81. # ======================================================================
  82.  
  83.  
  84. ########################################################################
  85. ########## Configurable variables ######################################
  86.  
  87. $SENDMAIL = '/usr/lib/sendmail';
  88. #                                   The location of your sendmail binary
  89.  
  90. @AUTHDOMAINS = ('');
  91. #           List of lower-case Internet domains that can use this script 
  92. #                                such as ('ncsa.uiuc.edu', 'domain.com')
  93.  
  94. ## Also, make sure the first line of this script points
  95. ## to your PERL binary
  96.  
  97. ########## Nothing else to change ######################################
  98. ########################################################################
  99.  
  100.  
  101. $ENV{'SCRIPT_NAME'} =~ m#(/.*/)(.*)$#;
  102. $SCRIPTDIR = $1;
  103. $SCRIPT = $2;
  104.  
  105. #### Do standard HTTP stuff ####
  106. &cgi_receive;
  107. &cgi_decode;
  108. &cgi_header;
  109.  
  110. #### Load mail.list into associative array ####
  111. open (MAILNAMES, "mail.list") || die ("$SCRIPT: Can't open mail.list: $!\n");
  112. while (<MAILNAMES>) {
  113.     chop;
  114.     ($nick, $addr) = split(/:/, $_);
  115.     $ADDRESS{$nick} = $addr;
  116. }
  117. close (MAILNAMES);
  118.  
  119. #### Figure out who the information should be sent to ####
  120. if ($ENV{'QUERY_STRING'} =~ /\@/) {
  121.     #### User specified a full email address ####
  122.     ($machine = $') =~ tr/A-Z/a-z/;
  123.     undef $FLAG{'authorized'};
  124.     for ($[ .. $#AUTHDOMAINS) {
  125.     $FLAG{'authorized'} = $AUTHDOMAINS[$_], last if ($ENV{'QUERY_STRING'} =~ /$AUTHDOMAINS[$_]$/);
  126.     }
  127.     &error_blank_field('an authorized email address') unless ($FLAG{'authorized'});
  128.     $recipient = $ENV{'QUERY_STRING'};
  129.     $extraaction = "?$recipient";
  130. }
  131. elsif ($ENV{'QUERY_STRING'}) {
  132.     #### User specified a nickname ####
  133.     $nickname = $ENV{'QUERY_STRING'};
  134.     &error_blank_field('a valid recipient nickname') unless ($ADDRESS{$nickname});
  135.     $recipient = $ADDRESS{$nickname};
  136.     $extraaction = "?$nickname";
  137. }
  138. elsif ($FORM{'nickname'}) {
  139.     #### Input is coming from listbox, ready for forwarding ####
  140.     $nickname = $FORM{'nickname'};
  141.     &error_blank_field('a valid recipient nickname') unless ($ADDRESS{$nickname});
  142.     $recipient = $ADDRESS{$FORM{'nickname'}};
  143. }
  144. elsif ($ENV{'REQUEST_METHOD'} eq "POST") {
  145.     #### I don't know who the information was for ####
  146.     &error_blank_field('a valid recipient');
  147. }
  148.  
  149. #### Output a default email form if not POSTing already ####
  150. &print_form unless ($ENV{'REQUEST_METHOD'} eq "POST");
  151.  
  152. #### Check for require fields
  153. foreach $field (@requirefields) {
  154.     &error_blank_field($field) unless ($FORM{$field});
  155. }
  156.  
  157. #### Fill in missing fields for forwarding FORM results ####
  158. ($FORM{'subject'}) || ($FORM{'subject'} = "FORM results");
  159. ($FORM{'from-email'}) || ($FORM{'from-email'} = $recipient);
  160. ($FORM{'from-name'}) || ($FORM{'from-name'} = "WebMonitor mail");
  161.  
  162. open (MAIL, "| $SENDMAIL $recipient") || die ("$SCRIPT: Can't open $mailprog: $!\n");
  163. print MAIL "Reply-to: $FORM{'from-email'} ($FORM{'from-name'})\n";
  164. print MAIL "From: $FORM{'from-email'} ($FORM{'from-name'})\n";
  165. print MAIL "To: $recipient\n";
  166. print MAIL "Subject: $FORM{'subject'}\n";
  167. print MAIL "X-Comments: =============================================================\n";
  168. print MAIL "X-Comments: NOTE:  This message was sent through the WebMonitor mail form\n";
  169. print MAIL "X-Comments: =============================================================\n";
  170. print MAIL "X-Comments: HOST:      $ENV{'REMOTE_HOST'} ($ENV{'REMOTE_ADDR'})\n";
  171. print MAIL "X-Comments: BROWSER:   $ENV{'HTTP_USER_AGENT'}\n";
  172. print MAIL "X-Comments: REFERER:   $FORM{'previous-url'}\n" if ($FORM{'previous-url'});
  173. print MAIL "X-Comments: =============================================================\n";
  174. print MAIL "\n";
  175. &dump_values(FORM, MAIL);
  176. print MAIL "\n";
  177. close (MAIL);
  178.  
  179. #### Now, redirect if "next-url" is included
  180. if ($FORM{'next-url'}) {
  181.     print "Location: $FORM{'next-url'}\n";
  182.     print "\n";
  183.     exit;
  184. }
  185.  
  186. #### Prevent HTML output
  187. foreach $key (keys %FORM) {
  188.     $FORM{$key} =~ s/</\</g;
  189.     $FORM{$key} =~ s/>/\>/g;
  190. }
  191.  
  192. #### Output confirmation message ####
  193. print qq|<HTML><HEAD><TITLE>WebMonitor-Email Sent</TITLE></HEAD><BODY>\n|;
  194. print qq|<H1>$ENV{'SERVER_NAME'} Email Sent</H1>\n|;
  195. print qq|The following message has been sent.\n|;
  196. print qq|You can now return to <A HREF="$FORM{'previous-url'}">where you were</A>.\n| if ($FORM{'previous-url'});
  197. print qq|<HR>\n|;
  198. print "<PRE>\n";
  199. print "Reply-to: $FORM{'from-email'} ($FORM{'from-name'})\n";
  200. print "From: $FORM{'from-email'} ($FORM{'from-name'})\n";
  201. print "To: $recipient\n";
  202. print "Subject: $FORM{'subject'}\n";
  203. print "\n";
  204. &dump_values(FORM, STDOUT);
  205. print "\n";
  206. print "</PRE>\n";
  207. print "</BODY></HTML>\n";
  208. exit;
  209.  
  210. #####################################################################
  211. #### SUBROUTINES ####################################################
  212.  
  213. sub error_blank_field {
  214.     local($variable) = @_;
  215.     print "\n" if ($FORM{'next-url'});
  216.     print "<HTML><HEAD><TITLE>WebMonitor-Email Error</TITLE></HEAD><BODY>\n";
  217.     print "<H1>Error!</H1>\n";
  218.     print "You did not fill in $variable.\n";
  219.     print "</BODY></HTML>\n";
  220.     exit;
  221. }
  222.  
  223. sub cgi_header {
  224.     print "Content-type: text/html\n";
  225.     print "\n" unless ($FORM{'next-url'});
  226. }        
  227.  
  228. sub cgi_receive {
  229.     if ($ENV{'REQUEST_METHOD'} eq "POST") {
  230.         read(STDIN, $incoming, $ENV{'CONTENT_LENGTH'});
  231.     }
  232.     else {
  233.         $incoming = $ENV{'QUERY_STRING'};
  234.     }
  235. }
  236.  
  237. sub cgi_decode {
  238.     @pairs = split(/&/, $incoming);
  239.  
  240.     foreach (@pairs) {
  241.         ($name, $value) = split(/=/, $_);
  242.  
  243.         $name  =~ tr/+/ /;
  244.         $value =~ tr/+/ /;
  245.         $name  =~ s/%([A-F0-9][A-F0-9])/pack("C", hex($1))/gie;
  246.         $value =~ s/%([A-F0-9][A-F0-9])/pack("C", hex($1))/gie;
  247.  
  248.         #### Strip out semicolons unless for special character
  249.         $value =~ s/;/$$/g;
  250.         $value =~ s/&(\S{1,6})$$/&\1;/g;
  251.         $value =~ s/$$/ /g;
  252.  
  253.         $value =~ s/\|/ /g;
  254.         $value =~ s/^!/ /g; ## Allow exclamation points in sentences
  255.  
  256.     #### Split apart any directive prefixes
  257.     #### NOTE: colons are reserved to delimit these prefixes
  258.     @parts = split(/:/, $name);
  259.     $name = $parts[$#parts];
  260.     if (grep(/^require$/, @parts)) {
  261.         push (@requirefields, $name);
  262.     }
  263.     if (grep(/^ignore$/, @parts)) {
  264.         push (@ignorefields, $name);
  265.     }
  266.     if (grep(/^dynamic$/, @parts)) {
  267.         #### For simulating a checkbox
  268.         #### It may be dynamic, but useless if nothing entered
  269.             next if ($value eq "");
  270.             $name = $value;
  271.             $value = "on";
  272.     }
  273.  
  274.         #### Skip generally blank fields
  275.         next if ($value eq "");
  276.  
  277.     #### Allow for multiple values of a single name
  278.         $FORM{$name} .= ", " if ($FORM{$name});
  279.  
  280.         $FORM{$name} .= $value;
  281.     #### Add to ordered list if not on list already
  282.         push (@fields, $name) unless (grep(/^$name$/, @fields));
  283.     }
  284. }
  285.  
  286. sub dump_values {
  287.     local($env, $handle) = @_;
  288.     ($handle eq "STDOUT") && (print $handle "<PRE>\n");
  289.     foreach $field (@fields) {
  290.     next if (grep(/^$field$/, @ignorefields));
  291.     if ($FORM{$field} =~ /[\cM\n]/) {
  292.         print $handle "($field)\n";
  293.         print $handle "-" x 75, "\n", $FORM{$field}, "\n", "-" x 75, "\n";
  294.     }
  295.     else {
  296.             print $handle "($field)  $FORM{$field}\n";
  297.     }
  298.     }
  299.     ($handle eq "STDOUT") && (print $handle "</PRE>\n");
  300. }
  301.  
  302. sub print_form {
  303.     print qq|<HTML><HEAD><TITLE>WebMonitor-Email Form</TITLE></HEAD><BODY>\n|;
  304.     print qq|<H1>$ENV{'SERVER_NAME'} <A HREF="http://hoohoo.ncsa.uiuc.edu/webmonitor/module-mail.html">Email Form</A></H1>\n|;
  305.     print qq|<FORM METHOD="POST" ACTION="$ENV{'SCRIPT_NAME'}$extraaction">\n|;
  306.     print qq|<HR>\n|;
  307.     print qq|<INPUT TYPE="submit" VALUE="Send Email"> to |;
  308.  
  309.     if ($nickname) {
  310.     print qq|<I>$recipient</I> <B>($nickname)</B>\n|;
  311.     }
  312.     elsif ($recipient) {
  313.     print qq|<I>$recipient</I>\n|;
  314.     }
  315.     else {
  316.     print qq|<SELECT NAME="ignore:nickname">\n|;
  317.     print qq|<OPTION>Select name...\n|;
  318.         foreach $nick (sort keys %ADDRESS) {
  319.         print qq|<OPTION>$nick\n|;
  320.         }
  321.         print qq|</SELECT>\n|;
  322.     }
  323.  
  324.  
  325.     print qq|<HR>\n|;
  326.     print qq|<PRE>|;
  327.     print qq|    Your Name: <INPUT NAME="require:ignore:from-name" SIZE="30">\n|;
  328.     print qq|Email Address: <INPUT NAME="require:ignore:from-email" SIZE="30">\n|;
  329.     print qq|      Subject: <INPUT NAME="ignore:require:subject" SIZE="40">    <INPUT TYPE="reset" VALUE="Clear Message">\n|;
  330.     print qq|</PRE>\n|;
  331.     print qq|<TEXTAREA NAME="require:message" ROWS="15" COLS="75"></TEXTAREA>\n|;
  332.     print qq|<INPUT TYPE="hidden" NAME="ignore:previous-url" VALUE="$ENV{'HTTP_REFERER'}">\n|;
  333.     print qq|</FORM>\n|;
  334.     print qq|</BODY></HTML>\n|;
  335.  
  336.     exit;
  337. }
  338.  
  339.